package fun.yao.common.nio;

import fun.yao.common.Constant;
import fun.yao.common.uitls.ConfigUtil;
import fun.yao.common.uitls.LogUtil;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;

/**
 * Socket端口监听服务线程
 */
public final class SocketServerThread extends AbstractNetThread
{
    /** 服务端套接字通道 */
    private ServerSocketChannel ssc = null ;
    /**监听端口*/
    private int iListenPort = 0 ;
    /**监听IP地址*/
    private String sListenIp = "";

    private boolean bIsInit = false;

    //-------------------------------------------------------------------------  构造函数
    /**
     * 构造函数
     */
    public SocketServerThread()
    {

    }

    /**
     * 构造函数
     * @param iListenPort  监听端口
     */
    public SocketServerThread(int iListenPort)
    {
        setListenAddress("",iListenPort);
    }

    /**
     * 构造函数
     * @param sListenIp    监听的本地IP地址
     * @param iListenPort  监听端口
     */
    public SocketServerThread(String sListenIp, int iListenPort)
    {
        setListenAddress(sListenIp,iListenPort);
    }

    //-------------------------------------------------------------------------  设置监听地址和端口
    /**
     * 设置服务监听端口
     * @param iListenPort 监听端口
     */
    public void setListenAddress(int iListenPort)
    {
        this.iListenPort = iListenPort;
    }

    /**
     * 设置服务监听的本地IP地址和监听端口
     * @param sListenIp     本地监听的IP地址
     * @param iListenPort   监听端口
     */
    public void setListenAddress(String sListenIp, int iListenPort)
    {
        this.sListenIp = sListenIp;
        this.iListenPort = iListenPort;
        LogUtil.writeSystemLog(Constant.NOTICE,"SetListenAddress-[" + this.sListenIp + "," + this.iListenPort + "]");
    }

    //-------------------------------------------------------------------------  初始化与关闭
    /**
     * 初始化，起动监听服务
     */
    public synchronized void init() throws Exception
    {
        try{

            if ( bIsInit == true )
                return ;

            int backlog = ConfigUtil.getConfigByInt("SERVERSOCKET_LISTEN_BACKLOG_SIZE", 1000);
            mSelector = Selector.open();

            // 初始化服务端套接字通道
            ssc = ServerSocketChannel.open();
            InetSocketAddress address = null ;
            if ( this.sListenIp.length() > 0 )
                address = new InetSocketAddress(this.sListenIp,this.iListenPort);
            else
                address = new InetSocketAddress(this.iListenPort);

            ssc.socket().setReuseAddress(true);
            ssc.socket().bind(address,backlog);

            // 配置非阻塞方式
            ssc.configureBlocking(false);

            // 向selector注册该channel的连接事件
            ssc.register(mSelector, SelectionKey.OP_ACCEPT);

            LogUtil.writeSystemLog(Constant.NOTICE,"启动监听服务[" + this.sListenIp + "," + this.iListenPort + "]成功.");

            bIsInit = true;

        }catch(Exception e){
            LogUtil.WriteLog(Constant.BADLY_ERROR,"启动监听服务[" + this.sListenIp + "," + this.iListenPort + "]失败.");
            throw e;
        }

    }


    /**
     * 关闭监听的相关服务
     */
    public void close()
    {
        try{
            bIsRun = false;
            if ( mSelector != null )
                mSelector.close();
            if ( ssc != null )
                ssc.close();
            LogUtil.writeSystemLog(Constant.NOTICE,"关闭监听服务[" + this.iListenPort + "]");
        }catch(Exception e)
        {
            LogUtil.WriteLog(Constant.BADLY_ERROR,e);
        }
    }
}
